package com.example.demo.mail;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import jodd.mail.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.jupiter.api.Test;

import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class MailDownloader {
    @Test
    @SneakyThrows
    public void download() {
        Pop3Server popServer = MailServer.create()
                .host("pop.qq.com")
                .port(995)
                .ssl(true)
                .auth("464961686@qq.com", "kudrkvjmgebnbhjc")
                .buildPop3MailServer();

        Pop3Server popServer1 = MailServer.create()
                .host("pop.exmail.qq.com")
                .port(995)
                .ssl(true)
                .auth("evie.zhou@bayblue.hk", "ZmMkr3MbTauHABPb")
                .buildPop3MailServer();

        ReceiveMailSession session = popServer1.createSession();
        session.open();
        int total = session.getMessageCount();
        System.out.println(total);

        String[] allFolders = session.getAllFolders();
        for (String folder : allFolders) {
            System.out.println("folder name: " + folder);
        }

        session.useFolder("INBOX");

        long startTime = getOffsetDate(-228);
        long endTime = getOffsetDate(0);


        System.out.println("filter emails between " + DateUtil.formatDateTime(new Date(startTime)) + " to " + DateUtil.formatDateTime(new Date(endTime)));
        EmailFilter emailFilter = EmailFilter.filter()
                .sentDate(EmailFilter.Operator.GE, startTime)
                .sentDate(EmailFilter.Operator.LE, endTime);
        System.out.println("begin receive email");
        File dir = new File("C:\\Users\\blysin\\Documents\\emails");
        AtomicInteger count = new AtomicInteger();
        session.receiveEmail(null, e -> {
            System.out.println("download email:" + count.incrementAndGet() + "/" + total);
            doDownload(e, dir);
        });


//        callback(emails);
        session.close();
    }

    private void callback(ReceivedEmail[] emails) {
        File dir = new File("C:\\Users\\blysin\\Documents\\emails");
        for (ReceivedEmail email : emails) {
            try {
                doDownload(email, dir);
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }

    private void doDownload(ReceivedEmail email, File dir) {
        System.out.println("\n\n===[" + email.messageNumber() + "]===");

        // common info
        Date sendDate = null;
        try {
            System.out.print("FROM:" + parsePersonInfo2(email.from()));
            System.out.print(", SUBJECT:" + email.subject());
            sendDate = email.sentDate();
            System.out.println(", SENT DATE:" + DateUtil.formatDateTime(sendDate));
        } catch (Exception e) {
            System.out.println("解析失败：" + e.getMessage());
        }

        // process attachments
        List<EmailAttachment<?>> attachments = email.attachments();
        if (CollectionUtils.isNotEmpty(attachments)) {
            System.out.println("附件列表...");

            //解析sendDate，获取月份和日期
            try {
                String mouth = DateUtil.format(sendDate, "MM");
                String day = DateUtil.format(sendDate, "dd");
                File file = new File(dir, mouth + File.separator + day + File.separator + processFolderName(email.subject()));
                FileUtil.mkdir(file);
                for (EmailAttachment<?> attachment : attachments) {
                    System.out.print("name: " + attachment.getName());
                    attachment.writeToFile(
                            new File(file, attachment.getName()));
                }
            } catch (Exception e) {
                System.out.println("附件下载失败：" + e.getMessage());
            }
        } else {
            System.out.println("不存在附件，跳过");
        }
    }

    @SneakyThrows
    private PersonInfo parsePersonInfo2(EmailAddress from) {
        try {
            return parsePersonInfo(from.toString());
        } catch (AddressException e) {
            System.out.println("解析失败：" + e.getMessage());
        }
        return new PersonInfo("", "");
    }

    /**
     * 获取相对于当前日期偏移指定天数后的日期的时间戳
     *
     * @param offsetDays 偏移的天数，可以是正数（表示未来日期）或负数（表示过去日期）
     * @return 返回偏移后日期的时间戳
     */
    private long getOffsetDate(int offsetDays) {
        // 获取当前时间的时间戳
        long currentTimestamp = System.currentTimeMillis();
        // 计算偏移后的日期的时间戳
        return currentTimestamp + (long) offsetDays * 24 * 60 * 60 * 1000;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class PersonInfo {
        private String name;
        private String email;

        @Override
        public String toString() {
            return name + "(" + email + ")";
        }
    }

    private PersonInfo parsePersonInfo(String from) throws AddressException {
        InternetAddress address = new InternetAddress(from);
        String personal = address.getPersonal();
        String email = address.getAddress();

        return new PersonInfo(personal, email);
    }

    /**
     * 处理文件夹名称，使其符合Windows文件夹命名规则。
     *
     * @param originalName 原始文件夹名称
     * @return 合法的文件夹名称
     */
    public static String processFolderName(String originalName) {
        String processedName = originalName.replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9]", "");

        // 限制长度为255个字符（Windows系统的限制）
        if (processedName.length() > 255) {
            processedName = processedName.substring(0, 255);
        }

        return processedName;



        /*// 替换非法字符为空格
        String processedName = originalName.replaceAll("[<>:\"/\\\\|?*]", " ");

        // 移除连续的空格并替换为单个空格
        processedName = processedName.replaceAll("\\s+", " ").trim();

        // 如果处理后的名称为空或只包含空格，则返回默认名称
        if (processedName.isEmpty()) {
            processedName = "DefaultFolder";
        }

        // 限制长度为255个字符（Windows系统的限制）
        if (processedName.length() > 255) {
            processedName = processedName.substring(0, 255);
        }

        processedName = processedName.replaceAll(" ", "");

        return processedName;*/
    }

    @Test
    @SneakyThrows
    public void parseName() {
        String name = "理货报告100modus 退货1   50534414700431711\r142\t571938449281520458591343393444840762192134439223992457078341935111828917741596346440052989113006419363431374242877953448755756262229939193326362502183038719328143824223170773442474477304549729345707845453373752419427876423440843741938963075255963380192837331343059477419408339924194091751932931849909045781346360500108101590434543239131919259253454997365329450659194188652642608739919402522687789040873448976691375748419343435532650531115034551696617172649293444288876146375324多品牌周露梦黄秋瑜福建泉州跨境仓";
        String result = processFolderName(name);
        System.out.println(result);

    }
}
